#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         DatetimeSelectorInfo.py
#
# Copyright:    Copyright (c) 2006, Faulkner Technologies
#
# Author:       Tinh Truong
#
# Description:  A DatetimeSelector is a simple Component that permits capturing
#               of date time information during the process of assessment
#####################################################################

#####################################################################
## Knowledge Engine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Component import Component, ComponentInfo
from Products.KnowledgeEngine.Assessible import Assessible
from Products.KnowledgeEngine.AssessmentComponentState import AssessmentComponentState
from Products.KnowledgeEngine.AssessmentComponentValueTypes import *
from Products.KnowledgeEngine.KERLExtensions import KERLExtensions
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *
from Products.KnowledgeEngine.KERFProcessor import *

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from ImageFile import ImageFile
from Products.Archetypes.public import *
from DateTime import DateTime

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## TextBoxInfo Class Definition
class DatetimeSelectorInfo(ComponentInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """

    #---------------------------------------------------------------#
    
    def getClassName(self):
        """
            Return the class name
        """
        
        return 'DatetimeSelector'

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """
    
        return "DatetimeSelector"
        
    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.  
        """
        
        return "datetimeselector"
        
    #---------------------------------------------------------------#
    
    def getClassIcon(self):
        """
            Return the appropriate icon file for the class.
        """
        
        return ImageFile('skins/DatetimeSelector_icon.gif', globals())
        

    #---------------------------------------------------------------#

    def isInstanceOf(self, className):
        """
            Returns if the class is an instance of the specified
            className, or implements the interface specified 
            by the className
        """        
        return className == 'Assessible' or ComponentInfo.isInstanceOf(self, className)
    
    #---------------------------------------------------------------#

    def onConfigureProperties(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register 
            class specific properties using the PropertyReflection interface.
            
            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered
            
            NOTE: This method is called before ClassInfo.onAfterStartup()            
        """
        #initialise the super-class properties for reflection
        ComponentInfo.onConfigureProperties(self)
        
        #add the 'reportContent' property        
        self.addPropertyDefinition(PropertyDefinition(identity="reportContent", displayName="Report Content", description="Text to be displayed for this component when used in a report", defaultValue="", propertyType=pt_STRING, propertyFormat=pf_HTML, propertyStructure=ps_ATOMIC))        
        
        self.addPropertyDefinition(PropertyDefinition(identity="defaultDatetime", displayName="Default DateTime", defaultValue='now', description="Set the default datetime (eg. set the date to today 'now' or set 30 day from now 'now + 30'", propertyFormat=pf_TEXT_SINGLELINE))


    #---------------------------------------------------------------#

#####################################################################
## DatetimeSelector Class Definition
class DatetimeSelector(Component, Assessible, KERLExtensions):
    """
        Defines a simple component to represent one or more lines of 
        text entered during an assessment.
    """

    #---------------------------------------------------------------#

    #TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = DatetimeSelectorInfo()
    
    #---------------------------------------------------------------#

    # DTML Methods
    index_html = DTMLFile('dtml/index_html', globals())
    simplereport_html = DTMLFile('dtml/simplereport_html', globals())

    #---------------------------------------------------------------#

    def __init__(self, id, identity):
        "Constructor for the DatetimeSelector"        
        
        Component.__init__(self, id, identity)

    #---------------------------------------------------------------#
    
    def getDefaultDatetime(self):
        "Returns the component assessment default value"         
        
        return self.defaultDatetime

    #---------------------------------------------------------------#
    
    def setDefaultDatetime(self, defaultDatetime):
        "Returns the component assessment default value"         
        
        self.defaultDatetime = defaultDatetime
    #---------------------------------------------------------------#

    def onAfterIdentityChange(self, identityMappings):
        """
            Handle Knowledge Engine specific actions after the 
            identity of this object has changed.
            
            The identityMappings dictionary holds 
            mappings from oldIdentities -> newIdentities
            (including this object)
                        
        """
        #perform default identity changes
        Component.onAfterIdentityChange(self, identityMappings)

    #---------------------------------------------------------------#

    def onAfterInstanciation(self):
        """
            Handle Knowledge Engine specific actions after this object 
            has been loaded into memory.  
            
            This is useful for performing backwards compatibility
        """
        #perform default onAfterInstanciation for the parent
        Component.onAfterInstanciation(self)
        
        #add maximumLength attribute if it doesn't already exist
        if not hasattr(self, "defaultDatetime"):
            self.defaultDatetime = "now"
        
    #---------------------------------------------------------------#
        
    def getComponentProperty(self, identity, propertyName, assessment = None):
        """
            Returns the value of the specified property, given the
            identity of the component (which may be used to lookup states) and
            an assessment.

            RETURNS: None if the property doesn't exist
        """
        if propertyName == "value":
            return assessment.getComponentState(identity).getValue()
        else:
            return Component.getComponentProperty(self, identity, propertyName, assessment)
       
    #---------------------------------------------------------------#
    # BEGIN: Assessible Implementation                              #
    #---------------------------------------------------------------#
        
    def getAssessmentValueType(self):
        """
            ABSTRACT: Returns the type of the value that is to be stored
            for this component when it's assessment state is persisted.
            
            NOTE 1: See AssessmentComponentValueTypes for a list of defined contants       
            NOTE 2: This method MUST be overriden in the implementing
            class to specify the correct type for value persistence
            
            RETURN TYPE: String
        """
        #textbox assessment values are strings
        return st_STRING
        
    #---------------------------------------------------------------#
        
    def convertDateTime(self):
        """
            Convert a string to the appropriate date and time
           
            NOTE: the possible entered value are 
                  'now' - which represent the current date and time
                  'now+10' - in 10days time
        """ 
        dateTime = ""
        valueComponent = None

        value = self.defaultDatetime
        
        if len(value) > 0:
           if value.find('+') != -1:
              valueComponent = value.split('+')
              d = DateTime() + valueComponent[1]
              dateTime = d.strftime("%Y-%m-%d %I:%M %p")
           elif value.find('-') != -1:
              valueComponent = value.split('-')
              d = DateTime() - valueComponent[1]
              dateTime = d.strftime("%Y-%m-%d %I:%M %p")              
           else:
              d = DateTime()
              dateTime = d.strftime("%Y-%m-%d %I:%M %p")
                  
        return dateTime
    #---------------------------------------------------------------#
        
    def getDefaultAssessmentState(self, assessment):
        """
            ABSTRACT: Constructs and returns a suitable 'default' 
            AssessmentComponentState for the provided Assessment
            instance.

            NOTE: This method MUST be overriden in the implementing
            class to provide a suitable default value for the component
            
            RETURN TYPE: AssessmentComponentState
        """
        return AssessmentComponentState(assessment.getIdentity(), assessment.getModelIdentity(), self.getIdentity(), self.getAssessmentValueType(), self.getDefaultDatetime())
            
    #---------------------------------------------------------------#

    def updateAssessmentState(self, assessment, formValue):
        """
            ABSTRACT: Updates the specified assessment using
            the provided HTTP REQUEST formValue.
            
            NOTE: This method MUST be overriden in the implementing
            class to suitably update the component state
        """
        print "updateAssessmentComponentState: ", formValue

        #get the current assessment state for the component from the assessment
        state = assessment.getComponentState(self.getIdentity())
        
        #update the current state
        state.setValue(formValue)
        
        #update the assessment
        assessment.setIsModified(true)

    #---------------------------------------------------------------#
    # END: Assessible Implementation                                #
    #---------------------------------------------------------------#
    
    #---------------------------------------------------------------#
    # BEGIN: KERLExtensions Implementation                          #
    #---------------------------------------------------------------#

    def compileKERLtoJavaScript(self, expression):
        """
            Returns a Python string that represents a JavaScript
            expression, which may be used to evaluate the status
            of the component class specific KERL expression.

            NOTE: this method is primarily used to produce
            JavaScript expressions that form the basis of the
            client-side showif technology.
            
            RETURN TYPE: String         
        """
        #example: cond="['datetimeselector','after', '2006-10-03']" returns 'document.getElementById("datetimeselector").value.indexOf(value)>=0'
        #example: cond="['datetimeselector','before', '2006-10-03']" returns 'document.getElementById("datetimeselector").value.indexOf(value)<0'
        #example: cond="['datetimeselector','dateis', '2006-10-03']" returns 'document.getElementById("datetimeselector").value==value'
        #example: cond="['datetimeselector','timeis', '10:10am']" returns 'document.getElementById("datetimeselector").value!=value'

        print "compileKERLtoJavaScript"

        #get the identity for each component since year, month, date, time are all in a separated field
        identity = self.getIdentity()
	yearIdentity = identity + "_year"
	monthIdentity = identity + "_month"
	dayIdentity = identity + "_day"
	hourIdentity = identity + "_hour"
	minuteIdentity = identity + "_minute"
	ampmIdentity = identity + "_ampm"

        #dateTime = d.strftime("%Y-%m-%d %I:%M %p")              
#	dateTime = year + "-" + "-" + month + "-" + day + " " + "hour" + ":" + minute + ":00 " + ampm
#	date = year + "-" + "-" + month + "-" + day + " " + "hour" + ":" + minute + ":00 " + ampm

#        storeDateTime = self.getDefaultDatetime();

#        resDateTime = DateTime(storeDateTime);
#        resDate = resDateTime.strftime("%Y-%m-%d")
#        resTime = resDateTime.strftime("%I:%M %p")              

        #get the operator
        opr = expression[1]

        #get the value
#        value = asJavaScript(expression[2])

#        print "EX2: ", expression[2]
#        print "EX1: ", expression[1]
#        print "EX0: ", expression[0]
#        print "DATE: ", DateTime(expression[2])
#        print "RESDATETIME: ", resDateTime
#        print "RESDATE: ", resDate
#        print "RESTIME: ", resTime
#        print "STOREDATE: ", storeDateTime

        dateComponent=()
        timeInExpression = ""
        hour = ""
        minute = ""
        ampm = ""
        # get value from KERL expression
        valueInExpression = expression[2]

        #get date value in show if expression
        dateInExpression = ""
        if opr in ("after","before","dateis"):
            dateObj = DateTime(valueInExpression)
        
        if opr in ("timeis"):
            timeObj = DateTime(valueInExpression)

        if opr == "after":
            print "AFTER: "
            dateExp = dateObj.strftime("%Y%m%d")
            textVal = "(parseInt(document.getElementById(\"%s\").value + document.getElementById(\"%s\").value + document.getElementById(\"%s\").value) > %s)" % (yearIdentity, monthIdentity, dayIdentity, dateExp)
            return textVal

        elif opr == "before":
            print "BEFORE: "
            dateExp = dateObj.strftime("%Y%m%d")
            textVal = "(parseInt(document.getElementById(\"%s\").value + document.getElementById(\"%s\").value + document.getElementById(\"%s\").value) < %s)" % (yearIdentity, monthIdentity, dayIdentity, dateExp)
            return textVal
        
        elif opr == "dateis":
            print "DATEIS: "
            dateExp = dateObj.strftime("%Y%m%d")
            textVal = "(parseInt(document.getElementById(\"%s\").value + document.getElementById(\"%s\").value + document.getElementById(\"%s\").value) == %s)" % (yearIdentity, monthIdentity, dayIdentity, dateExp)
            return textVal
        
        elif opr == "timeis":
            print "TIMEIS: "
            timeExp = timeObj.strftime("%I%M%p")
            textVal = "(document.getElementById(\"%s\").value + document.getElementById(\"%s\").value + document.getElementById(\"%s\").value == \"%s\")" % (hourIdentity, minuteIdentity, ampmIdentity, timeExp)
#            textVal = "(document.getElementById(\"%s\").value == \"%s\" && document.getElementById(\"%s\").value == \"%s\" && document.getElementById(\"%s\").value.toLowerCase() == \"%s\")" % (hourIdentity, asJavaScript(hour), minuteIdentity, asJavaScript(minute), ampmIdentity, asJavaScript(ampm.lower()))
            return textVal
        
        else:
            return "true"

    #---------------------------------------------------------------#

    def compileKERLtoEnglish(self, expression):
        """
            Returns a string representing an 'English' version
            of the component class specific KERL expression.

            NOTE: this method is primarily used to produce
            English descriptions of KERL expressions that may be 
            used to describe things like AssessmentFilters
            
            RETURN TYPE: String         
        """
        print "compileKERLtoEnglish"
        return ""

    #---------------------------------------------------------------#

    def evaluate(self, expression, assessment):
        """
            Evalutes the component class specific KERL expression
            using the provided assessment.

            NOTE: this method is primarily used to produce
            JavaScript expressions that form the basis of the
            client-side showif technology.

            RETURN TYPE: Boolean         
        """
        print "evaluate"
        print "EX0: ", expression[0]
        print "EX1: ", expression[1]
        print "EX2: ", expression[2]

        #get the identity
        identity = self.getIdentity()

        #get the operator
        opr = expression[1]

        #get the value in the show if expression
        valueInExpression = expression[2]

        #get date value in show if expression
        dateInExpression = ""
        if opr in ("after","before","dateis"):
            dateInExpression = valueInExpression

        #get time value in show if expression
        timeInExpression = ""
        if opr in ("timeis"):
            dateTimeInExpression = DateTime(valueInExpression)
            timeInExpression = dateTimeInExpression.strftime("%I:%M %p")
 
        #get the stored state
        state = assessment.getComponentState(identity)
        assessmentValue = state.getValue()

        # split datetime into separate component
        dateTimeInAssessment = DateTime(assessmentValue);
        dateInAssessment = dateTimeInAssessment.strftime("%Y-%m-%d")
        timeInAssessment = dateTimeInAssessment.strftime("%I:%M %p")              

        print "ORI VAL IN EXP VALUE: ", valueInExpression
        print "ORI VAL IN ASS VALUE ", assessmentValue
        print "ASS DATETIME OBJ: ", dateTimeInAssessment
        print "ASS DATE ", dateInAssessment
        print "ASS TIME ", timeInAssessment

        #evaluate the expression
        if opr == "after":
            # We only need to compare the date only to make sure if the date is greater then the show if date expression
            print "EV AFTER: ", DateTime(dateInAssessment) > DateTime(dateInExpression)
            return DateTime(dateInAssessment) > DateTime(dateInExpression)
        
        elif opr == "before":
            print "BEFORE: ", DateTime(dateInAssessment) < DateTime(dateInExpression)
            return DateTime(dateInAssessment) < DateTime(dateInExpression)
        
        elif opr == "dateis":
            print "DATE: ", DateTime(dateInAssessment) == DateTime(dateInExpression)
            return DateTime(dateInAssessment) == DateTime(dateInExpression)
        
        elif opr == "timeis":
            print "ASST: ", timeInAssessment
            print "STORE: ", timeInExpression
            print "TIME: ", timeInAssessment == timeInExpression
            return timeInAssessment == timeInExpression
        
        else:
            return "true"
    
    #---------------------------------------------------------------#

    def getDependencies(self, expression):
        """
            Returns a list of components that are required to
            evaluate the component class specific KERL expression.

            NOTE: Includes the specific component itself.

            RETURN TYPE: {Component} indexed by Component.getIdentity()
       """
        print "getDependencies"
        return {self.getIdentity():self}
    
    #---------------------------------------------------------------#

    def updateKERLIdentities(self, expression, identityMappings):
        """
            Returns the expression with the appropriate old identities
            (as identified by the identityMappings) replaced with 
            new identities.
        """
        #get the component identity from the expression (first element)
        identity = expression[0]
        
        #is the component in the identityMappings?
        if identityMappings.has_key(identity):
            expression[0] = identityMappings[identity]
       
        print "updateKERLIdentities" 
        return expression

    #---------------------------------------------------------------#
    # END: KERLExtensions Implementation                            #
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

# Register Component Information with the Knowledge Engine
registerGenericObjectClass(DatetimeSelector)

#####################################################################
